<template>
	<div class="sqlBox">
		<div style="display: flex; align-items: center">
			<el-switch
				v-model="debuged"
				:active-value="true"
				:inactive-value="false"
				inline-prompt
				style="--el-switch-on-color: #8aa0ff; --el-switch-off-color: #cec5be; margin-right: 5px"
				active-text="关闭调试"
				inactive-text="打开调试"
			/>
			<el-tooltip class="box-item" effect="dark" :content="sqlTip" placement="top-start">
				<el-icon :size="20"><InfoFilled /></el-icon>
			</el-tooltip>
		</div>
		<div class="sqlTopBox" v-if="debuged">
			<div>
				<el-button text @click="handleFormat()"><img src="@/assets/format.png" /></el-button>
				<el-button :loading="executeSqlButton" @click="executeSql()" text><img src="@/assets/run.png" /></el-button>
			</div>
			<div>
				<el-button size="small" type="warning" round @click="addTag('trim')">trim</el-button>
				<el-button size="small" type="warning" round @click="addTag('if')">if</el-button>
				<el-button size="small" type="warning" round @click="addTag('where')">where</el-button>
				<el-button size="small" type="warning" round @click="addTag('foreach')">foreach</el-button>
			</div>
		</div>
		<div class="sqlMiddleBox">
			<div class="sqlLeftBox">
				<div id="sqlCodeEditBox"></div>
			</div>
			<div class="rightResize"></div>
			<div class="sqlRightBox">
				<JsonStudio ref="JsonStudioRef"></JsonStudio>
			</div>
		</div>
		<div class="sqlBottomBox" v-if="debuged">
			<el-tabs class="sqlBottomTabs">
				<el-tab-pane>
					<template #label>
						<span class="sqlCustomTabsLabel">
							<el-icon> <Postcard /> </el-icon>&nbsp;
							<span>执行结果</span>
						</span>
					</template>
					<ConsoleResult ref="consoleResultRef"></ConsoleResult>
				</el-tab-pane>
			</el-tabs>
			<el-divider></el-divider>
		</div>
	</div>
</template>

<script lang="ts" setup>
import jsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker'
import cssWorker from 'monaco-editor/esm/vs/language/css/css.worker?worker'
import htmlWorker from 'monaco-editor/esm/vs/language/html/html.worker?worker'
import tsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker?worker'
import EditorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker'
import * as monaco from 'monaco-editor'
import { format } from 'sql-formatter'
import { language as sqlLanguage } from 'monaco-editor/esm/vs/basic-languages/html/html.js'
import { nextTick, ref, onBeforeUnmount, onMounted, inject } from 'vue'
import JsonStudio from './json-studio.vue'
import ConsoleResult from '../../data-development/production/console-result.vue'
import { ElMessage } from 'element-plus/es'
import { executeSqlApi } from '@/api/data-service/apiConfig'

const text = ref('')
const language = ref('sql')
const editorTheme = ref('vs-dark')
const executeSqlButton = ref(false)

const debuged = ref(false)
const apiSqlForm = inject('apiSqlForm')

const sqlTip = `SQL语句：
SELECT * FROM people
<where>
  <if test="ids != null and ids.size() != 0">
       id IN
      <foreach collection="ids" index="index" item="item" open="(" close=")" separator=",">
          #{item}
      </foreach>
  </if>
  </if>
    and uk = #{uk}
  </if>
</where>
`

//
// MonacoEditor start
//
onBeforeUnmount(() => {
	editor.dispose()
	sqlCompletion.dispose()
	console.log('editor dispose')
})

onMounted(() => {
	editorInit()
	console.log('editor init')
})

const sqlCompletion = monaco.languages.registerCompletionItemProvider('sql', {
	provideCompletionItems: function () {
		let suggestions = []
		sqlLanguage.keywords.forEach(item => {
			suggestions.push({
				label: item,
				kind: monaco.languages.CompletionItemKind.Keyword,
				insertText: item
			})
		})
		sqlLanguage.operators.forEach(item => {
			suggestions.push({
				label: item,
				kind: monaco.languages.CompletionItemKind.Operator,
				insertText: item
			})
		})
		sqlLanguage.builtinFunctions.forEach(item => {
			suggestions.push({
				label: item,
				kind: monaco.languages.CompletionItemKind.Function,
				insertText: item
			})
		})
		sqlLanguage.builtinVariables.forEach(item => {
			suggestions.push({
				label: item,
				kind: monaco.languages.CompletionItemKind.Variable,
				insertText: item
			})
		})
		return {
			suggestions: suggestions
		}
	}
})

// @ts-ignore
self.MonacoEnvironment = {
	getWorker(_: string, label: string) {
		if (label === 'json') {
			return new jsonWorker()
		}
		if (label === 'css' || label === 'scss' || label === 'less') {
			return new cssWorker()
		}
		if (label === 'html' || label === 'handlebars' || label === 'razor') {
			return new htmlWorker()
		}
		if (['typescript', 'javascript'].includes(label)) {
			return new tsWorker()
		}
		return new EditorWorker()
	}
}
let editor = null
//从父组件获取当前每个tab对应的值和编辑的tab名称
/* const editorValues = inject("editorValues")
const editableTabsValue = inject("editableTabsValue") */

const editorInit = () => {
	nextTick(() => {
		!editor
			? (editor = monaco.editor.create(document.getElementById('sqlCodeEditBox') as HTMLElement, {
					value: text.value, // 编辑器初始显示文字
					language: language.value, // 语言支持自行查阅demo
					automaticLayout: true, // 自适应布局
					theme: editorTheme.value, // 官方自带三种主题vs, hc-black, or vs-dark
					foldingStrategy: 'indentation',
					renderLineHighlight: 'all', // 行亮
					selectOnLineNumbers: true, // 显示行号
					minimap: {
						enabled: true
					},
					cursorStyle: 'line', //光标样式
					readOnly: false, // 只读
					fontSize: 16, // 字体大小
					autoIndent: true, //自动布局
					useTabStops: false,
					quickSuggestionsDelay: 100, //代码提示延时
					scrollBeyondLastLine: false, // 取消代码后面一大段空白
					overviewRulerBorder: false // 不要滚动条的边框
			  }))
			: editor.setValue('')
		// console.log(editor)
		// 监听值的变化
		/* editor.onDidChangeModelContent((val:any) => {
					  //editor.trigger('', 'editor.action.triggerSuggest', {});
						text.value = editor.getValue();
						//把当前最新的数据放入缓存
						if(editorValues[editableTabsValue.value]) {
							editorValues[editableTabsValue.value]["codeText"] = text.value
						}
						//console.log(editorValues)
				}) */
		//sql提醒
		sqlCompletion
	})
}

const addTag = (tagVal: any) => {
	let editorVal = getEditorValue()
	editorVal = editorVal ? editorVal + '\n' : ''
	if (tagVal == 'trim') {
		setEditorValue(editorVal + '<trim prefix="" suffix="" suffixesToOverride="" prefixesToOverride=""></trim>')
	} else if (tagVal == 'if') {
		setEditorValue(editorVal + '<if test="" ></if>')
	} else if (tagVal == 'where') {
		setEditorValue(editorVal + '<where></where>')
	} else if (tagVal == 'foreach') {
		setEditorValue(editorVal + '<foreach open="(" close=")" collection="" separator="," item="item" index="index">#{item}</foreach>')
	}
}

const consoleResultRef = ref()
const JsonStudioRef = ref()
const executeSql = () => {
	const sqlDto = {}
	sqlDto.openTrans = apiSqlForm.openTrans
	sqlDto.sqlDbType = apiSqlForm.sqlDbType
	sqlDto.databaseId = apiSqlForm.databaseId
	sqlDto.statement = getEditorValue()
	sqlDto.sqlSeparator = apiSqlForm.sqlSeparator
	sqlDto.sqlMaxRow = apiSqlForm.sqlMaxRow
	if (!sqlDto.sqlDbType) {
		ElMessage.warning('请选择数据库类别')
		return
	}
	if (!sqlDto.sqlSeparator) {
		ElMessage.warning('sql分隔符不能为空')
		return
	}
	if (!sqlDto.sqlDbType) {
		ElMessage.warning('请选择数据库类型')
		return
	}
	if (!sqlDto.databaseId && sqlDto.sqlDbType == 1) {
		ElMessage.warning('请选择数据库')
		return
	}
	if (!sqlDto.statement) {
		ElMessage.warning('请输入sql语句')
		return
	}
	if (!sqlDto.sqlMaxRow) {
		ElMessage.warning('请输入最大查询条数')
		return
	}
	sqlDto.jsonParams = JsonStudioRef.value.getEditorValue()
	executeSqlButton.value = true
	executeSqlApi(sqlDto)
		.then(res => {
			consoleResultRef.value.init(res.data, '1', false)
		})
		.finally(() => {
			executeSqlButton.value = false
		})
}

// @ts-ignore
//切换语言
const changeLanguage = () => {
	monaco.editor.setModelLanguage(editor.getModel(), language.value)
	//  editor.updateOptions({
	//           language: "objective-c"
	//       });
}
//切换主题
const handleTheme = () => {
	monaco.editor.setTheme(editorTheme.value)
}
//格式化sql
const handleFormat = () => {
	editor.setValue(format(editor.getValue(), { language: 'mysql' }))
}

const setEditorValue = (value: any) => {
	editor.setValue(value)
}

const getEditorValue = () => {
	return editor.getValue()
}

const getSqlParam = () => {
	return JsonStudioRef.value.getEditorValue()
}

const setSqlParam = (value: any) => {
	JsonStudioRef.value.setEditorValue(value)
}

const closeDebug = () => {
	debuged.value = false
}

/***
 * editor.setValue(newValue)

editor.getValue()

editor.onDidChangeModelContent((val)=>{ //监听值的变化  })

editor.getAction('editor.action.formatDocument').run()    //格式化代码

editor.dispose()    //销毁实例

editor.onDidChangeOptions　　//配置改变事件

editor.onDidChangeLanguage　　//语言改变事件
 */
defineExpose({
	setEditorValue,
	getEditorValue,
	handleFormat,
	getSqlParam,
	setSqlParam,
	closeDebug
})
</script>

<style scoped>
#sqlCodeEditBox {
	margin-top: 0;
	width: 100%;
	height: 360px;
}

.sqlTopBox {
	display: flex;
	margin-bottom: 8px;
}

.sqlMiddleBox {
	display: flex;
	position: relative;
}

.sqlMiddleBox .rightResize {
	position: relative;
	background-color: #d6d6d6;
	border-radius: 5px;
	width: 5px;
	height: 360px;
	background-size: cover;
	background-position: center;
	/*z-index: 99999;*/
	font-size: 32px;
	color: white;
}

.sqlLeftBox {
	width: 50%;
}

.sqlRightBox {
	position: absolute;
	top: -40px;
	right: 0;
	width: calc(50% - 5px);
	height: 360px;
}

/* .sqlBottomBox {
	height: 200px;
} */
.sqlBottomTabs {
	height: 100%;
}

.sqlBottomTabs > .el-tabs__content {
	height: calc(100% - 40px);
	padding: 0;
}

/* 每个tab高度设置为100% */
.sqlBottomTabs > .el-tabs__content > .el-tab-pane {
	height: 100%;
}

.sqlBottomTabs .sqlCustomTabsLabel {
	font-size: 16px;
}

.sqlBottomTabs > .el-tabs__header {
	padding: 0;
	position: relative;
	margin: 0 0 0;
}
</style>
